package org.example.myl.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.example.myl.expection.AppException;
import org.example.myl.expection.ResponseCode;
import org.example.myl.zhujie.RateLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class RateLimitAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    // 默认最大请求次数和时间窗口
    @Value("${rate.limit.max.requests:5}")
    private int maxRequests;

    @Value("${rate.limit.time.window:60}")
    private int timeWindow;

    @Pointcut("@annotation(org.example.myl.zhujie.RateLimit)")  // 拦截带有 @RateLimit 注解的方法
    public void rateLimitPointcut() {}

    @Before("rateLimitPointcut() && @annotation(rateLimit)")
    public void checkRateLimit(RateLimit rateLimit) throws AppException {
        // 获取请求的 IP 地址
        String ip = getClientIp();  // 这里的实现需要根据实际情况来获取 IP 地址

        // 如果注解上有自定义配置，优先使用注解的配置
        int maxRequestsForMethod = rateLimit.maxRequests();
        int timeWindowForMethod = rateLimit.timeWindow();

        String key = "rate_limit:" + ip;

        // 获取当前请求次数
        String currentCount = redisTemplate.opsForValue().get(key);

        if (currentCount == null) {
            // 如果没有记录，则是第一次请求，设置初始值为 1，并设置过期时间
            redisTemplate.opsForValue().set(key, "1", timeWindowForMethod, TimeUnit.SECONDS);
        } else {
            int count = Integer.parseInt(currentCount);
            if (count >= maxRequestsForMethod) {
                throw new AppException(ResponseCode.OUTTIME.getCode(),ResponseCode.OUTTIME.getInfo());
            }
            // 增加请求次数
            redisTemplate.opsForValue().increment(key, 1);
        }
    }

    // 获取客户端 IP 地址的简单示例
    private String getClientIp() {
        // 这里可以通过 request.getRemoteAddr() 或者获取 HTTP 请求头中的 X-Real-IP 来获取 IP 地址
        return "127.0.0.1";  // 模拟 IP 地址
    }
}

